﻿namespace _01单例模式.反射破坏单例模式
{

    /// <summary>
    /// 解决反射创建对象的问题
    /// </summary>
    public class SingleLayMan3
    {
        //2、声明静态字段  存储我们唯一的对象实例
        private volatile static SingleLayMan3? _singleLayMan;
        private static object _oj = new object();
        //私有化构造函数
        private SingleLayMan3()
        {
            lock (_oj)
            {
                if (_singleLayMan != null)
                {
                    throw new Exception("不要通过反射来创建对像！");
                }
            }
        }

        /// <summary>
        /// //解决多线程安全问题，双重锁定，减少系统消耗，节约资源
        /// </summary>
        public static SingleLayMan3 GetSingleLayMan()
        {
            if (_singleLayMan == null)
            {
                lock (_oj)
                {
                    if (_singleLayMan == null)
                    {
                        _singleLayMan = new SingleLayMan3();
                        Console.WriteLine("我被创建了一次！");
                    }
                }
            }           
            return _singleLayMan;
        }
       
    }

    public class SingleLayManTest3
    {
        /// <summary>
        /// 第一次通过调用 SingleLayMan3.GetSingleLayMan()创建对象导致_singleLayMan不为空，之后再去通过反射创建对象时，构造函数里面判断创建对象导致_singleLayMan变量，报异常
        /// </summary>
        public static void FactTestReflection()
        {
            var singleLayMan1= SingleLayMan3.GetSingleLayMan();

            var type = Type.GetType("_01单例模式.反射破坏单例模式.SingleLayMan3");
            //获取私有的构造函数
            var ctors = type?.GetConstructors(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
            //执行构造函数
            SingleLayMan3 singleLayMan = (SingleLayMan3)ctors[0].Invoke(null);
            Console.WriteLine(singleLayMan1.GetHashCode());
            Console.WriteLine(singleLayMan.GetHashCode());
        }
    }
}
